﻿using DatabaseModificationSync.Entities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace DatabaseModificationSync
{
    public class Bootstrapper
    {
        List<DatabaseVersion> versions;

        bool hasExecuted;

        string rawDataPath = string.Empty;

        public Bootstrapper(string connectionString)
        {
            SqlHelper.DBConnectionString = connectionString;
        }

       
        public void PrepareSync()
        {
            Prefix();
            rawDataPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ModificationHistory.json");
            if (!File.Exists(rawDataPath))
            {
                SimpleLog.Error("未发现配置文件:ModificationHistory.json,程序将退出",null);
                return;
            }
            string serialText = File.ReadAllText(rawDataPath);
            versions = JsonConvert.DeserializeObject<List<DatabaseVersion>>(serialText);
            
            var creatTableItem = versions[0];
            string err = "";
            try
            {
                //SqlHelper.ExecuteNonQuery(metaCmd.Statements);
                SqlHelper.DBContext.Ado.ExecuteCommand(creatTableItem.Statement);
            }
            catch (Exception ex)
            {
                SimpleLog.Error("执行失败:{metaCmd.Statements}",ex);
                err = ex.Message;
            }
            finally
            {
                creatTableItem.RESULT = err;
                AddOrUpdateVersion(creatTableItem);
                CheckVersion();
            }
        }

        private void Prefix()
        {
            Console.WriteLine("数据库结构同步@JQSOFT");
            Console.WriteLine("Create By @Stardance");
        }

        private void CheckVersion()
        {
            var db = SqlHelper.DBContext;
            var datas = db.Queryable<DatabaseVersion>().ToList();
            List<int> unexecutedStatements = versions.Select(it => it.ID).ToList().Except(datas.Select(it => it.ID)).ToList();
            List<DatabaseVersion> prepareChangeVers = versions.Where(it => unexecutedStatements.Contains(it.ID)).OrderBy(it => it.ID).ToList();
            if (!prepareChangeVers.Any())
            {
                string info = "数据库全部更变已同步！";
                SimpleLog.Info(info);
                //Console.WriteLine(info);
                return;
            }
            SimpleLog.Info($"发现待执行语句{prepareChangeVers.Count}条.");
            //Console.WriteLine($"发现待执行语句{prepareChangeVers.Count}条.{Environment.NewLine}");
            foreach (var item in prepareChangeVers)
            {
                Exception exx = null;
                var ret = 0;
                try
                {
                    SimpleLog.Info($"准备执行SQL语句(ID:{item.ID}):{item.Statement}");
                    //ret = SqlHelper.ExecuteNonQuery(item.Statements);
                    ret = db.Ado.ExecuteCommand(item.Statement);
                    if (ret >= 1) hasExecuted = true;
                }
                catch (Exception ex)
                {
                    exx = ex;
                    SimpleLog.Error($"SQL执行未成功(ID:{item.ID}):", ex);
                }
                finally
                {
                    if (exx == null)
                    {
                        SimpleLog.Info($"SQL语句(ID:{item.ID})执行完成！{Environment.NewLine}");
                        //Console.WriteLine($"SQL语句(ID:{item.ID})执行完成！{Environment.NewLine}");
                    }
                    //SQL不允许单引号中包括单引号，添加转义
                    item.Statement = item.Statement.Replace("'", "''");
                    //item.CreateTime = item.CreateTime.Replace("T", " ");
                    //string executeResultCmd = $"INSERT INTO databaseversion values({item.ID},'{item.Statement}','{item.CreateTime.Replace("T"," ")}',1,{(exx == null ? 0 : 1)},'{item.Description}')";
                    //SqlHelper.ExecuteNonQuery(executeResultCmd);
                    if (exx != null)
                    {
                        item.RESULT = exx.Message;
                    }
                    AddOrUpdateVersion(item);
                }
            }
        }

        public void AddOrUpdateVersion(DatabaseVersion ver)
        {
            var db = SqlHelper.DBContext;
            if(db.Queryable<DatabaseVersion>().Any(it => it.ID == ver.ID))
            {
                //update
                ver.ExecuteTime = DateTime.Now;
                db.Updateable<DatabaseVersion>(ver)
                  .Where(it => it.ID == ver.ID)
                  .ExecuteCommand();
            }
            else
            {
                //insert
                ver.ExecuteTime = DateTime.Now;
                db.Insertable<DatabaseVersion>(ver).ExecuteCommand();
            }
        }
    }
}
